package org.sciom

import org.sciom.v1.ScIomInterpreter
import org.sciom.evaluation.EvaluationWaiter
import org.sciom.parser.ScIomParser

object ScIomState {
  val MESSAGE_STOP_STATUS_NORMAL = 0
  val MESSAGE_STOP_STATUS_BREAK = 1
  val MESSAGE_STOP_STATUS_CONTINUE = 2
  val MESSAGE_STOP_STATUS_RETURN = 4
  val MESSAGE_STOP_STATUS_EOL = 8

  def getState() = {
    new ScIomState
  }
}

class ScIomState {
//	PHash *primitives;

  val objectProto = new ScIomObject(this)

  val ioNil = new ScIomNil(this)
  val ioTrue = new ScIomTrue(this)
  val ioFalse = new ScIomFalse(this)

//	IoObject *ioNormal;
//	IoObject *ioBreak;
//	IoObject *ioContinue;
//	IoObject *ioReturn;
//	IoObject *ioEol;

  var symbols = Map[String, ScIomSymbol]() // TODO: Should be a weak hash map.

  val activateSymbol = new ScIomSymbol(this,"activate")
  val forwardSymbol = new ScIomSymbol(this,"forward")
  val selfSymbol = new ScIomSymbol(this,"self")
  val setSlotSymbol = new ScIomSymbol(this,"setSlot")
  val setSlotWithTypeSymbol = new ScIomSymbol(this,"setSlotWithType")
  val updateSlotSymbol = new ScIomSymbol(this,"updateSlot")
  val callSymbol = new ScIomSymbol(this,"call")
  val typeSymbol = new ScIomSymbol(this,"type")
  val opShuffleSymbol = new ScIomSymbol(this,"opShuffle")
  val noShufflingSymbol = new ScIomSymbol(this,"__noShuffling__")
  val semicolonSymbol = new ScIomSymbol(this,";")
  val stackSizeSymbol = new ScIomSymbol(this,"stackSize")

  val seqProto = new ScIomSymbol(this, "seqProto")
  seqProto.rawSetProto(objectProto)

//	IoObject *setSlotBlock;
//	IoObject *localsUpdateSlotCFunc;
//	IoObject *localsProto;

//	IoMessage *collectedLinkMessage;
//	IoMessage *compareMessage;
//	IoMessage *willFreeMessage;
//	IoMessage *initMessage;
//	IoMessage *mainMessage;
//	IoMessage *nilMessage;
//	IoMessage *runMessage;
//	IoMessage *printMessage;
//	IoMessage *yieldMessage;

  val opShuffleMessage = new ScIomMessage(this, opShuffleSymbol, null)

  val lobby = objectProto.IOCLONE
  val core = objectProto.IOCLONE
  val protos = objectProto.IOCLONE

  lobby.setSlotTo(symbolWithString("Lobby"), lobby)
  lobby.setSlotTo(symbolWithString("Protos"), protos)
  protos.setSlotTo(symbolWithString("Core"), core)
  protos.setSlotTo(symbolWithString("Addons"), objectProto.IOCLONE)
  core.setSlotTo(symbolWithString("Compiler"), new ScIomCompiler(this))
  core.setSlotTo(symbolWithString("Exception"), objectProto.IOCLONE)

  objectProto.rawSetProto(lobby)
  lobby.rawSetProto(protos)
  protos.rawSetProto(core)

  core.setSlotTo(symbolWithString("Object"), objectProto)

  var stopStatus : int = ScIomState.MESSAGE_STOP_STATUS_NORMAL
  var returnValue : ScIomObject = ioNil

  seqProto.protoFinish

  def doString(value: String) : ScIomObject = {
    lobby.doString(value)
//    var parser = ScIomParser.parserFor(value)
//    new EvaluationWaiter(parser)._with(interpreter)
  }

  def symbolWithStringAndLength(value: String, length: int) : ScIomSymbol = {
    if(symbols.contains(value)) {
      return symbols(value)
    }

    val symbol = ScIomSequence.newSymbolWithString(this, value)
    return addSymbol(symbol)
  }

  def symbolWithString(value: String) : ScIomSymbol = symbolWithStringAndLength(value, value.length)

  // Io: IONUMBER
  def number(value: int) = new ScIomNumber(this, value)

  def addSymbol(value: ScIomSymbol) : ScIomSymbol = {
    symbols = symbols(value.string) = value
    value
  }

  // Io: IoState_error_
  def error(m: ScIomMessage, format: String, args: Any*) : ScIomObject = {
    val description = symbolWithString(StringUtils.newWithFormat(format, args.toArray))

    ScIomCoroutine.raiseError(this, description, m)
    m
  }
}

